package winOrDie.GameEngine.Client;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;


import winOrDie.Net.WoD_Net_Protocol_ASCII;
import winOrDie.Net.Client.WoD_Client_ControlChannel;
import winOrDie.Net.Client.WoD_Client_ControlChannel_Event;
import winOrDie.Net.Client.WoD_Client_ControlChannel_Listener;
import winOrDie.Net.Client.WoD_Peers_List;
import winOrDie.Net.Client.WoD_Client_RT;
import winOrDie.Net.Client.WoD_Client_RT_Event;
import winOrDie.Net.Client.WoD_Client_RT_Listener;

public class WoD_Client_Test 
implements WoD_Client_ControlChannel_Listener, WoD_Client_RT_Listener
{
	private String username = null;
	private int ID = -1;
	
	private WoD_Peers_List woDPeersList = null;
	private Socket socket = null;
	private int udp_RT_Port = -1;
	private WoD_Client_RT woDClientRT = null;
	
	
	private int server_RT_Port = -1;
	
	private int tcp_backup = -1;
	
	/**
	 * The control channel thread
	 */
	private WoD_Client_ControlChannel woDClientControlChannel = null;
	
	
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public WoD_Client_ControlChannel getWoDClientControlChannel() {
		return woDClientControlChannel;
	}

	public int getTcp_backup() {
		return tcp_backup;
	}

	public void setTcp_backup(int tcpBackup) {
		tcp_backup = tcpBackup;
	}

	public int getUdp_RT_Port() {
		return udp_RT_Port;
	}

	public void setUdp_RT_Port(int udpRTPort) {
		udp_RT_Port = udpRTPort;
	}

	public WoD_Client_Test() {
		woDPeersList = new WoD_Peers_List();
	}
	

	public void connectToWoDServer(String hostName, int port) throws Exception
	{
		try {
			socket = new Socket(hostName, port);
		} catch (UnknownHostException e) {
			Exception exception = new Exception("Unknown host: " + hostName + ". " + e.getMessage());
			throw exception;
			
		} catch (IOException e) {
			Exception exception = new Exception("IO Error. " + e.getMessage());
			throw exception;
		}
		
		
		/*
		 * Start control channel thread
		 */
		try {
			woDClientControlChannel = new WoD_Client_ControlChannel(socket);
			woDClientControlChannel.add_WoD_Client_ControlChannel_Listener(this);
		} catch (Exception e) {
			Exception exception = new Exception("Error on control channel. " + e.getMessage());
			throw exception;
		}
		
		/*
		 * Start RT channel thread
		 */
		try {
			woDClientRT = new WoD_Client_RT(udp_RT_Port, 500, 10000);
			woDClientRT.add_WoD_Client_RT_Listener(this);
			woDClientRT.startClient();
		} catch (Exception e) {
			Exception exception = new Exception("Error on RT channel. " + e.getMessage());
			throw exception;
		}
		
		/*
		 * Send Join Game Message
		 */
		String message = WoD_Net_Protocol_ASCII.GameMenu.Join_Game + " ";
		message += username + " ";
		message += tcp_backup + " ";  
		message += udp_RT_Port;
		woDClientControlChannel.sendData(message);
	}
	
	
	public void notify_Event_WoD_Client_ControlChannel(
			WoD_Client_ControlChannel_Event event) {
		switch (event.getEvent_Type()) {
		
		case WoD_Client_ControlChannel_Event.CLIENT_ERROR:
			System.out.println("Error de cliente. " + (String)event.getData());
			break;
			
		case WoD_Client_ControlChannel_Event.JOIN_GAME_KO:
			System.out.println("Error al conectar. " + (String)event.getData());
			break;
			
		case WoD_Client_ControlChannel_Event.JOIN_GAME_OK:
			System.out.println("Se ha unido al juego. " + (String)event.getData());
			String message_parts[] = String.valueOf(event.getData()).split(" ");
			ID = Integer.valueOf(message_parts[1]);
			server_RT_Port = Integer.valueOf(message_parts[2]);
			
			break;
			
		
		case WoD_Client_ControlChannel_Event.CHAT:
			System.out.println("Mensaje de chat -> " + (String)event.getData());
			break;

		default:
			break;
		}
		
	}
	
	
	
	
	public void notify_Event_WoD_Client_RTChannel(WoD_Client_RT_Event event) {
		
		switch (event.getEvent_Type()) {
		case WoD_Client_RT_Event.ERROR_DATAGRAM:
			System.out.println("Datagram Error. " + event.getMessage());
			break;

		case WoD_Client_RT_Event.ERROR_IO:
			System.out.println("Datagram IO Error. " + event.getMessage());
			break;
		
		case WoD_Client_RT_Event.ERROR_PROTOCOL:
			System.out.println("Datagram protocol Error. " + event.getMessage());
			break;			

		case WoD_Client_RT_Event.GAME_ACTION:
			
			break;			

		case WoD_Client_RT_Event.GAME_NTP:
			
			String message_parts[] = event.getMessage().split(" ");
			final long server_sendTime = Long.valueOf(message_parts[1]);
			final long received_time = new Date().getTime();
			
			Thread thread = new Thread(new Runnable() {
				
				@Override
				public void run() {
					Thread.yield();
					
					long send_time = new Date().getTime();
					String message_To_Send = WoD_Net_Protocol_ASCII.RealTime.HEADER_SNTP + " ";
					message_To_Send += server_sendTime + " ";
					message_To_Send += received_time + " ";
					message_To_Send += send_time;
					
					try {
						woDClientRT.sendMessage(
								socket.getInetAddress().getHostAddress(), 
								server_RT_Port, 
								message_To_Send.getBytes());
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						return;
					}
					
				}
			});
			thread.start();
			
			break;			
			
		default:
			break;
		}
	}
	
	
	
	
	public void disconnect() throws Exception
	{
		String message = WoD_Net_Protocol_ASCII.GameRoom.Leave_Game;
		try {
			woDClientControlChannel.sendData(message);
		} catch (Exception e) {
			Exception exception = new Exception("Error while disconnecting. " + e.getMessage());
			throw exception;
		}
	}
	
}
